home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Power Programmierung
/
Power-Programmierung (Tewi)(1994).iso
/
magazine
/
msysjour
/
vol06
/
03
/
winedd
/
feeder.c
< prev
next >
Wrap
Text File
|
1991-05-01
|
10KB
|
293 lines
/* ----------------------------- FEEDER.C ----------------------------------
Embedded Device Driver Application.
Feeder (device simulator) module.
Spark Software Inc. 1991.
------------------------------------------------------------------------- */
/* The following is an intentionally empty definition; this is used to tell */
/* the compiler that we wish to have the global variables in "globals.h" */
/* declared in this source module and only defined in all others. */
#define PUBLIC
#include <windows.h>
#include <stdio.h>
#include <memory.h>
#include <dos.h>
#include "dprivate.h"
#include "device.h"
#include "intnum.h"
#include "logmsg.h"
#include "fdefs.h"
/* Public function prototypes. */
PUBLIC int PASCAL WinMain( HANDLE , HANDLE , LPSTR , int );
PUBLIC LONG FAR PASCAL FeederWndProc( HWND , WORD , WORD , LONG );
/* Private function prototypes. */
PRIVATE BOOL NEAR PASCAL Init( HANDLE );
PRIVATE LONG NEAR PASCAL DoTimer( VOID );
/* Private data object declarations. */
PRIVATE BOOL bEnded; /* Logger defunct? */
PRIVATE BYTE szAppName[ ] = APP_NAME; /* Application name. */
PRIVATE BYTE szClass[ ] = APP_CLASS; /* Window class name. */
PRIVATE BYTE szString[ 81 ]; /* Generic text buffer. */
PRIVATE WORD wCharWidth , wCharHeight; /* Font information. */
PRIVATE HANDLE hInst , hPrevInst; /* Handles to program instances. */
PRIVATE HWND hWndMaster; /* Handle of our master window. */
PUBLIC int PASCAL WinMain( hInstance , hPrevInstance , lpszCmdLine , nCmdShow )
HANDLE hInstance , hPrevInstance;
LPSTR lpszCmdLine;
int nCmdShow;
{
DWORD dwThisTime , dwPrevTime;
MSG Msg;
/* Call initialization procedure if this is the first instance. */
if( !hPrevInstance && !Init( hInstance ) )
return 0;
if( hPrevInstance )
{
/* See if the top-level window of this app still exists. */
GetInstanceData( hPrevInstance , (PSTR)&hWndMaster , sizeof hWndMaster );
if( IsWindow( hWndMaster ) )
{
/* We won't allow more than one invocation of this program. */
sprintf( szString , "%s already active." , APP_NAME );
MessageBox( GetFocus( ) , (LPSTR)szString , (LPSTR)szAppName , MB_OK | MB_ICONHAND );
return 0;
}
}
/* Create our top-level (i.e., master) window. */
hWndMaster = CreateWindow(
(LPSTR)szClass ,
(LPSTR)szAppName ,
WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN ,
CW_USEDEFAULT ,
0 ,
CW_USEDEFAULT ,
0 ,
(HWND)NULL ,
(HMENU)NULL ,
hInstance ,
(LPSTR)NULL
);
hInst = hInstance;
hPrevInst = hPrevInstance;
/* Show the window. */
ShowWindow( hWndMaster , nCmdShow );
/* Process messages from our queue. */
dwThisTime = dwPrevTime = GetTickCount( );
while( TRUE )
{
if( PeekMessage( (LPMSG)&Msg , NULL , 0 , 0 , PM_REMOVE ) )
{
if( Msg.message == WM_QUIT )
{
return (int)Msg.wParam;
}
TranslateMessage( (LPMSG)&Msg );
DispatchMessage( (LPMSG)&Msg );
}
/* NOTE: working in this part of the message loop allows */
/* us to process input when we have 0 or more messages. */
if( dwPrevTime + FEED_TIMER_INTERVAL <= ( dwThisTime = GetTickCount( ) ) )
{
/* Feed the device driver. */
DoTimer( );
dwPrevTime = dwThisTime;
}
}
}/* WinMain( ) */
/* Procedure called when the application is loaded for the first time */
PRIVATE BOOL NEAR PASCAL Init( hInstance )
HANDLE hInstance;
{
WNDCLASS Class;
/* Register the window class. */
Class.hCursor = LoadCursor( NULL, IDC_ARROW );
Class.hIcon = LoadIcon( hInstance , MAKEINTRESOURCE( APPICON ) );
Class.lpszMenuName = (LPSTR)NULL;
Class.lpszClassName = (LPSTR)szClass;
Class.hbrBackground = GetStockObject( WHITE_BRUSH );
Class.hInstance = hInstance;
Class.style = CS_HREDRAW | CS_VREDRAW;
Class.lpfnWndProc = FeederWndProc;
Class.cbClsExtra = 0;
Class.cbWndExtra = 0;
if( !RegisterClass( (LPWNDCLASS)&Class ) )
/* Initialization failed. */
return FALSE;
return TRUE;
}/* Init( ) */
PUBLIC LONG FAR PASCAL FeederWndProc( hWnd , wMessage , wParam , lParam )
HWND hWnd;
WORD wMessage;
WORD wParam;
LONG lParam;
{
PRIVATE WORD wLoggerDefunctMsg;
switch( wMessage )
{
case WM_CREATE:
bEnded = FALSE;
wLoggerDefunctMsg = RegisterWindowMessage( LOGGER_DEFUNCT_MSG );
return (LONG)1;
case WM_DESTROY:
PostQuitMessage( 0 );
return (LONG)1;
default:
if( wMessage == wLoggerDefunctMsg )
{
/* No interrupt handler; LOGGER has terminated. */
DestroyWindow( hWndMaster );
bEnded = TRUE;
return (LONG)1;
}
else
{
return DefWindowProc( hWnd , wMessage , wParam , lParam );
}
}
}/* FeederWndProc( ) */
PRIVATE LONG NEAR PASCAL DoTimer( )
{
PRIVATE WORD wIndex;
# ifdef INTERRUPT_DEVICE /* Feed the device via interrupt. */
# ifndef C6_ASM /* C 6.0 compiler supports _asm keyword. */
union REGS Regs;
struct SREGS SRegs;
# endif /* C6_ASM */
# endif /* INTERRUPT_DEVICE */
/* Have we destroyed our window? */
if( bEnded )
{
/* No interrupt handler; LOGGER has terminated. */
return (LONG)1;
}
/* Before invoking the interrupt handler, place a counter into */
/* AX so that we know data is being transferred properly. */
# ifdef INTERRUPT_DEVICE /* Feed the device via interrupt. */
# ifdef C6_ASM /* C 6.0 compiler supports _asm keyword. */
/* Set up the machine registers, execute an INT and notify the user. */
_asm
{
push ax ; Save register state.
push bx ;
push cx ;
push dx ;
push si ;
push di ;
mov ax , 0 ; Prepare to
lahf ; get the flags and
push ax ; put them on the stack too.
mov ax , wIndex ; Set up registers for the interrupt.
mov bx , 0 ;
mov cx , 0 ;
mov dx , 0 ;
mov si , 0 ;
mov di , 0 ;
int INTNUM ; Do the interrupt!
mov ax , 0 ;
push ax
call MessageBeep ; Beep.
pop ax ; Pop the flags and
sahf ; restore them.
pop di ; Restore register state.
pop si ;
pop dx ;
pop cx ;
pop bx ;
pop ax ;
}
# else /* C6_ASM */ /* V5.1 C compiler supports int86x only. */
/* NOTE: C 5.X doesn't work with Windows 3.0 here, because int86x( ) */
/* writes the INT instruction to the stack segment and executes */
/* it there (the only alternative would be to have a large "switch */
/* statment" in int86x( ) because the argument to INT must be a */
/* constant). When int86x( ) then tries to run the code written on */
/* the stack segment, a GP fault occurs because CODE SEGMENTS ARE */
/* READ-ONLY. If you must write code like this using C 5.1 and */
/* Windows 3.0, you must use MASM. */
Regs.x.ax = wIndex;
Regs.x.bx = Regs.x.cx = Regs.x.dx = Regs.x.si = Regs.x.di = 0;
Regs.x.cflag = 0;
segread( &SRegs );
int86x( INTNUM , &Regs ,&Regs , &SRegs );
MessageBeep( 0 );
# endif /* C6_ASM */
# else /* INTERRUPT_DEVICE */ /* Call the interrupt handler directly. */
/* NOTE: C DOES NOT guarantee us that the first 13 parameters passed */
/* to a function declared with the _interrupt keyword (or the alias */
/* interrupt) will be received as passed. The use of the _interrupt */
/* keyword directs the compiler to load those parameters directly from */
/* the machine registers before calling the function, ignoring what */
/* was passed if the function was called directly from an application. */
/* Arguments to be passed by a direct call should be appended to the */
/* parameter list (i.e. AFTER all 13 register parameters). */
INTHANDLER( 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 , wIndex , 0 , 0 , 0 );
# endif /* INTERRUPT_DEVICE */
/* Flash the application's icon. */
FlashWindow( hWndMaster , TRUE );
FlashWindow( hWndMaster , FALSE );
wIndex++;
return (LONG)1;
}/* DoTimer( ) */
/* EOF */